<template>
    <el-container>
        <el-main id="map" class="" style="display: flex;flex-direction: column;width: 100%;height: 100%;">
            <div v-if="tooltip.visible" :style="tooltipStyle" class="tooltip">
                经度: {{ tooltip.lng }}<br>
                纬度: {{ tooltip.lat }}
            </div>
        </el-main>
        <el-footer>
            <div class="rBottom">
                <div>
<!--                    <el-button @click="createAndClearRoute()" size="small" type="primary"-->
<!--                               :disabled="controlButtonDisable">开启编辑-->
<!--                    </el-button>-->

<!--                    <el-button @click="detailEdit()" v-show="detailEditButtonDisable" size="small"-->
<!--                               type="primary">轨迹调整-->
<!--                    </el-button>-->

<!--                    <el-button @click="editForbidden()" size="small"-->
<!--                               type="primary">{{forbiddenAction}}-->
<!--                    </el-button>-->
                    <el-button
                            size="small"
                            @click="toggleDrawingMode"
                            :style="{ background: isDrawing ? '#4CAF50' : '#f44336' }">
                        {{ isDrawing ? '停止绘制' : '上传禁飞区' }}
                    </el-button>
                </div>
            </div>
        </el-footer>
    </el-container>

</template>

<script>
    import mapboxgl from 'mapbox-gl';
    import * as THREE from 'three';

    export default {
        data() {
            return {
                isDrawing: false,
                map: null,
                scene: null,
                camera: null,
                renderer: null,
                cylinders: [],
                tooltip: {
                    visible: false,
                    lng: 0,
                    lat: 0,
                    x: 0,
                    y: 0
                },
                selectedObject: null,
                isDragging: false,
                modelTransform: {}
            };
        },
        computed: {
            tooltipStyle() {
                return {
                    left: this.tooltip.x + 15 + 'px',
                    top: this.tooltip.y + 15 + 'px'
                };
            }
        },
        mounted() {
            this.initMap();
        },
        beforeDestroy() {
            this.cleanup();
        },
        methods: {
            toggleDrawingMode() {
                this.isDrawing = !this.isDrawing;
            },

            initMap() {
                mapboxgl.accessToken = 'pk.eyJ1IjoiemhhbmdmZWkzMTcwIiwiYSI6ImNtNnlnMmZpZTBnenYydm9pOHQ0MzF6Y2oifQ.7aFdSnD7Ilm3P7PhyTMWtw';

                this.map = new mapboxgl.Map({
                    container: 'map',
                    style: 'mapbox://styles/mapbox/streets-v11?language=zh-Hans', // 地图样式
                    center: [118.75163, 32.046901], // 初始中心点坐标
                    zoom: 15, // 初始缩放级别
                    // pitch: 60,
                    // antialias: true
                });

                this.map.on('style.load', () => {
                    const layers = this.map.getStyle().layers;
                    const labelLayerId = layers.find(
                        (layer) => layer.type === 'symbol' && layer.layout['text-field']
                    ).id;

                    this.map.addLayer(
                        {
                            'id': 'add-3d-buildings',
                            'source': 'composite',
                            'source-layer': 'building',
                            'filter': ['==', 'extrude', 'true'],
                            'type': 'fill-extrusion',
                            'minzoom': 15,
                            'paint': {
                                'fill-extrusion-color': '#aaa',

                                // Use an 'interpolate' expression to
                                // add a smooth transition effect to
                                // the buildings as the user zooms in.
                                'fill-extrusion-height': [
                                    'interpolate',
                                    ['linear'],
                                    ['zoom'],
                                    15,
                                    0,
                                    15.05,
                                    ['get', 'height']
                                ],
                                'fill-extrusion-base': [
                                    'interpolate',
                                    ['linear'],
                                    ['zoom'],
                                    15,
                                    0,
                                    15.05,
                                    ['get', 'min_height']
                                ],
                                'fill-extrusion-opacity': 0.6
                            }
                        },
                        labelLayerId
                    );
                });

                this.map.addControl(new mapboxgl.ScaleControl(), 'bottom-left')

                this.map.on('load', () => {
                    this.initThree();
                    this.addEventListeners();
                });
            },

            initThree() {
                const canvas = this.map.getCanvas();
                this.scene = new THREE.Scene();
                this.camera = new THREE.PerspectiveCamera(
                    75,
                    window.innerWidth/window.innerHeight,
                    0.1,
                    1000);
                this.renderer = new THREE.WebGLRenderer({
                    canvas: canvas,
                    context: canvas.getContext("webgl"),
                    antialias: true
                });

                this.renderer.autoClear = false;
            },

            addEventListeners() {
                // 点击地图创建圆柱
                this.map.on('click', (e) => {
                    if (this.isDrawing) this.createCylinder(e.lngLat);
                });

                // 右键删除
                this.map.on('contextmenu', (e) => {
                    this.handleRightClick(e);
                });

                // 鼠标交互
                const canvas = this.map.getCanvas();
                canvas.addEventListener('mousemove', this.handleMouseMove);
                canvas.addEventListener('mousedown', this.handleMouseDown);
                canvas.addEventListener('mouseup', this.handleMouseUp);
            },

            createCylinder(lngLat) {
                // const modelOrigin = [lngLat.lng, lngLat.lat]
                // const modelAltitude = 0;
                // const modelRotate = [Math.PI / 2, 0, 0];
                // const modelScale = 5.41843220338983e-8;
                // this.modelTransform = {
                //     translateX: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).x,
                //     translateY: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).y,
                //     translateZ: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).z,
                //     rotateX: modelRotate[0],
                //     rotateY: modelRotate[1],
                //     rotateZ: modelRotate[2],
                //     scale: modelScale
                // };
                const {mercator} = this.lngLatToMercator(lngLat);
                const radius = this.calculateRadius(10); // 5公里半径
                const height = 200; // 200米高度

                const geometry = new THREE.CylinderGeometry(radius, radius, height, 32);
                // 添加材质
                const material = new THREE.MeshBasicMaterial({
                    color: '#fdff6e',
                    side: THREE.DoubleSide,
                    opacity: 0.5,
                    transparent: true
                });

                const cylinder = new THREE.Mesh(geometry, material);
                cylinder.position.set(mercator.x, mercator.y, height / 2);
                cylinder.userData = {
                    lngLat: lngLat,
                    radius: radius,
                    height: height,
                    isDraggable: true
                };
                const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
                directionalLight.position.set(0, 50, 100);
                this.scene.add(directionalLight);
                this.scene.add(cylinder);
                this.cylinders.push(cylinder);
                this.updateThree();
            },

            calculateRadius(km) {
                // 将公里转换为墨卡托坐标单位
                const center = this.map.project(this.map.getCenter());
                const offset = this.map.project([
                    this.map.getCenter().lng + km / 111,
                    this.map.getCenter().lat
                ]);
                return Math.abs(offset.x - center.x);
            },

            handleRightClick(e) {
                const intersect = this.getIntersectedObject(e);
                if (intersect && intersect.length > 0) {
                    this.scene.remove(intersect[0].object);
                    this.cylinders = this.cylinders.filter(cyl => cyl !== intersect[0].object);
                    this.updateThree();
                }
            },

            handleMouseMove(e) {
                // 工具提示
                const intersect = this.getIntersectedObject(e);
                if (intersect && intersect.length > 0) {
                    this.map.getCanvas().style.cursor = 'pointer';
                    const {lngLat} = intersect[0].object.userData;
                    const rect = this.map.getCanvas().getBoundingClientRect();
                    this.tooltip = {
                        visible: true,
                        lng: lngLat.lng.toFixed(4),
                        lat: lngLat.lat.toFixed(4),
                        x: e.clientX - rect.left,
                        y: e.clientY - rect.top
                    };
                } else {
                    this.map.getCanvas().style.cursor = '';
                    this.tooltip.visible = false;
                }

                // 拖动处理
                if (this.isDragging && this.selectedObject) {
                    const mouse = this.getMousePosition(e);
                    const raycaster = new THREE.Raycaster();
                    raycaster.setFromCamera(mouse, this.camera);

                    const plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
                    const intersection = new THREE.Vector3();
                    raycaster.ray.intersectPlane(plane, intersection);

                    this.selectedObject.position.copy(intersection);
                    this.updateCylinderGeoData(this.selectedObject);
                    this.updateThree();
                }
            },

            handleMouseDown(e) {
                const intersect = this.getIntersectedObject(e);
                if (intersect && intersect.length > 0 && intersect[0].object.userData.isDraggable) {
                    this.isDragging = true;
                    this.selectedObject = intersect.object;
                }
            },

            handleMouseUp() {
                this.isDragging = false;
                this.selectedObject = null;
            },

            updateCylinderGeoData(cylinder) {
                // 更新圆柱体的地理数据
                const coords = this.map.unproject([
                    cylinder.position.x + 65536,
                    cylinder.position.y + 65536
                ]);
                cylinder.userData.lngLat = coords;
            },

            getIntersectedObject(e) {
                const mouse = this.getMousePosition(e);
                const raycaster = new THREE.Raycaster();
                raycaster.setFromCamera(mouse, this.camera);
                const intersects = raycaster.intersectObjects(this.scene.children);
                return intersects;
            },

            getMousePosition(e) {
                const rect = this.map.getCanvas().getBoundingClientRect();
                return new THREE.Vector2(
                    ((e.clientX - rect.left) / rect.width) * 2 - 1,
                    -((e.clientY - rect.top) / rect.height) * 2 + 1
                );
            },

            lngLatToMercator(lngLat) {
                const {x, y} = this.map.project(lngLat);
                return {
                    mercator: new THREE.Vector3(x - 65536, y - 65536, 0)
                };
            },

            updateThree() {
                requestAnimationFrame(() => {
                    const transform = this.map.transform;
                    this.camera.projectionMatrix.fromArray(transform.projMatrix);
                    this.renderer.state.reset();
                    this.renderer.render(this.scene, this.camera);
                    this.map.triggerRepaint();
                });
            },

            cleanup() {
                const canvas = this.map.getCanvas();
                canvas.removeEventListener('mousemove', this.handleMouseMove);
                canvas.removeEventListener('mousedown', this.handleMouseDown);
                canvas.removeEventListener('mouseup', this.handleMouseUp);
                if (this.map) this.map.remove();
                if (this.renderer) this.renderer.dispose();

            }
        }
    };
</script>

<style scoped>
    .map-container {
        width: 100vw;
        height: 100vh;
        position: relative;
    }

    .control-button {
        position: absolute;
        top: 20px;
        left: 20px;
        z-index: 1000;
        padding: 10px 20px;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }

    .tooltip {
        position: absolute;
        background: rgba(255, 255, 255, 0.9);
        padding: 8px;
        border-radius: 4px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
        pointer-events: none;
        font-size: 12px;
    }

    .rBottom {
        /*margin-left: 2%;*/
        height: 13%;
        width: 96%;
        display: flex;
        justify-content: space-between;
        align-items: center;
        top: 2%;
    }

    #map .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl-scale {
        height: 10px;
        background-color: transparent !important;
        line-height: 10%;
        text-align: center
    }

    #map .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl-logo {
        display: none !important;
    }

    #map .mapboxgl-ctrl-bottom-right {
        display: none !important;
    }
</style>
